﻿
Imports std
Imports storoomc

Partial Public Class storoomOper

    Protected Overridable Function fullImpl(ByVal slices As vector(Of storageInterface)) As ternary
        Return threadModel().multiOper(d(Function(ByRef s As storageInterface) As ternary
                                             Return s.full()
                                         End Function),
                                       slices)
    End Function

    Protected Overridable Function retireImpl(ByVal slices As vector(Of storageInterface)) As Boolean
        Return threadModel().multiOper(d(Function(ByRef s As storageInterface) As ternary
                                             Return s.retire()
                                         End Function),
                                       slices)
    End Function

    Protected Overridable Function emptyImpl(ByVal slices As vector(Of storageInterface)) As ternary
        Return threadModel().multiOper(d(Function(ByRef s As storageInterface) As ternary
                                             Return s.empty()
                                         End Function),
                                       slices)
    End Function

    Protected Overridable Function closeImpl(ByVal slices As vector(Of storageInterface)) As Boolean
        Return threadModel().multiOper(d(Function(ByRef s As storageInterface) As ternary
                                             Return s.close()
                                         End Function),
                                       slices)
    End Function

    Protected Overridable Function openImpl(ByVal slices As vector(Of storageInterface)) As Boolean
        Return threadModel().multiOper(d(Function(ByRef s As storageInterface) As ternary
                                             Return s.open()
                                         End Function),
                                       slices)
    End Function

    Protected Overridable Function listImpl(ByVal l As vector(Of String),
                                            ByVal slices As vector(Of storageInterface)) As Boolean
        assert(Not l Is Nothing)
        Return threadModel().multiOper(d(Function(ByRef s As storageInterface,
                                                  ByRef this As vector(Of String)) As ternary
                                             If Not s.list(this) Then
                                                 this = Nothing
                                             End If
                                             Return ternary.true
                                         End Function),
                                       Function(ByRef this As vector(Of String)) As Boolean
                                           If this Is Nothing OrElse this.size() = 0 Then
                                               Return True
                                           End If
                                           Return l.push_back(this)
                                       End Function, slices)
    End Function

    Protected Overridable Function seekImpl(ByVal key As String, ByVal slices As vector(Of storageInterface)) As ternary
        Return threadModel().multiOper(d(Function(ByRef s As storageInterface) As ternary
                                             Return Not (s.seek(key))
                                         End Function),
                                       slices).reverse()
    End Function

    Protected Overridable Function readImpl(ByVal key As String,
                                            ByRef buff As bytes,
                                            ByVal slices As vector(Of storageInterface)) As Boolean
        Dim found As Boolean = False
        Return threadModel().multiOper(d(Function(ByRef s As storageInterface, ByRef this As bytes) As ternary
                                             If s.read(key, this) Then
                                                 found = True
                                             End If
                                             Return ternary.true
                                         End Function),
                                       Function(ByRef this As bytes, ByRef total As bytes) As Boolean
                                           total += this
                                           Return True
                                       End Function,
                                       slices, buff).true_() AndAlso Not buff Is Nothing AndAlso found = True
    End Function

    Protected Overridable Function deleteImpl(ByVal key As String,
                                              ByVal slices As vector(Of storageInterface)) As Boolean
        Dim deleted As Boolean = False
        Return threadModel().multiOper(d(Function(ByRef s As storageInterface) As ternary
                                             If s.delete(key) Then
                                                 deleted = True
                                             End If
                                             Return ternary.true
                                         End Function),
                                       slices).true_() AndAlso deleted
    End Function

    Protected Overridable Function sizeofImpl(ByVal key As String,
                                              ByRef size As UInt64,
                                              ByVal slices As vector(Of storageInterface)) As Boolean
        Dim rtn As Boolean = False
        size = 0
        Return threadModel().multiOper(d(Function(ByRef s As storageInterface, ByRef this As UInt64) As ternary
                                             this = 0
                                             If s.sizeof(key, this) Then
                                                 rtn = True
                                             End If
                                             Return ternary.true
                                         End Function),
                                       Function(ByRef this As UInt64, ByRef total As UInt64) As Boolean
                                           total += this
                                           Return True
                                       End Function,
                                       slices, size).true_ AndAlso rtn
    End Function

    Protected Overridable Function capacityImpl(ByRef cap As UInt64,
                                                ByVal slices As vector(Of storageInterface)) As Boolean
        Return threadModel().multiOper(d(Function(ByRef s As storageInterface, ByRef this As UInt64) As ternary
                                             Return s.capacity(this)
                                         End Function),
                                       Function(ByRef this As UInt64, ByRef total As UInt64) As Boolean
                                           total += this
                                           Return True
                                       End Function,
                                       slices, cap)
    End Function

    Protected Overridable Function valuesizeImpl(ByRef sz As UInt64,
                                                 ByVal slices As vector(Of storageInterface)) As Boolean
        Return threadModel().multiOper(d(Function(ByRef s As storageInterface, ByRef this As UInt64) As ternary
                                             Return s.valuesize(this)
                                         End Function),
                                       Function(ByRef this As UInt64, ByRef total As UInt64) As Boolean
                                           total += this
                                           Return True
                                       End Function,
                                       slices, sz)
    End Function

    Protected Overridable Function keycountImpl(ByRef count As UInt64,
                                                ByVal slices As vector(Of storageInterface)) As Boolean
        Return threadModel().multiOper(d(Function(ByRef s As storageInterface, ByRef this As UInt64) As ternary
                                             Return s.keycount(this)
                                         End Function),
                                       Function(ByRef this As UInt64, ByRef total As UInt64) As Boolean
                                           total += this
                                           Return True
                                       End Function,
                                       slices, count)
    End Function

    Protected Overridable Function writeImpl(ByVal key As String, ByVal buff As bytes, _
                                             ByRef slice As storageInterface, _
                                             ByVal slices As vector(Of storageInterface)) As Boolean
        slice = randomNotFullSlice(slices, Nothing)
        If slice Is Nothing Then
            raiseError("cannot get an empty and health slice to write in.", errorHandle.errorType.exclamation)
            Return False
        Else
            If threadModel().singleOper(Function(ByRef s As storageInterface) As ternary
                                            Return s.write(key, buff)
                                        End Function, slice) Then
                Return True
            Else
                raiseError("cannot write data to a not full slice, key " + key + ", slice " + showslice(slice), _
                           errorHandle.errorType.exclamation)
                Return False
            End If
        End If
    End Function

    Protected Overridable Function modifyImpl(ByVal key As String, ByVal buff As bytes, _
                                              ByRef slice As storageInterface, _
                                              ByVal slices As vector(Of storageInterface)) As Boolean
        If isdebugmode() Then
            Dim ss As vector(Of storageInterface) = Nothing
            Dim ws As vector(Of storageInterface) = Nothing
            ss = seekSelectSlices(key)
            ws = writeSelectSlices(key)
            assert(compare(ws, slices) = 0)
            assert(compare(ss, slices) = 0)
        End If

        Dim rtn As ternary = Nothing
        rtn = seekImpl(key, slices)
        If rtn = ternary.true Then
            If slices Is Nothing OrElse slices.size() = 0 Then
                'fall back to original logic to write to one of the slices, to make it safer,
                'but acturally, it should not go to here, there is a multilock to make the key safe
                'and modifyImpl should cover this, but save a call
                raiseError("storoomDistrOper.modifyImpl cannot get valid slices, even after storoomOper.seekImpl", _
                           errorHandle.errorType.exclamation)
                Return writeImpl(key, buff, slice, Me.slices)
            Else
                'copy the input slices to avoid change storoomDistrOper.slices
                'an assumption, slice/slice2/stornode .etc, all the storageInterface cannot be cloneable

                '20101223, 01:34
                'cannot erase the slice from slices, since
                'say, 2 nodes, 1 has the key, but 2 does not.
                'if selected 1 to modify, the deleteImpl will be failed.

                'Dim slices As vector(Of storageInterface) = Nothing
                'copy(slices, __slices)
                'Dim i As Int64
                'i = rnd(0, slices.size(), True)
                'slice = slices(i)
                'slices.erase(i)
                'Return (slices.size() = 0 OrElse deleteImpl(key, slices)) AndAlso slice.modify(key, buff)

                Return deleteImpl(key, slices) AndAlso slices(rnd(0, slices.size(), True)).write(key, buff)
            End If
        ElseIf rtn = ternary.false Then
            Return writeImpl(key, buff, slice, Me.slices)
        Else
            Return False
        End If
    End Function

    Protected Overridable Function syncImpl(ByVal host As String, ByVal port As Int32, _
                                            ByVal slices As vector(Of storageInterface)) As Boolean
        Dim i As Int64
        i = 0
        'slices may increase during sync, so just handle it
        While i < slices.size()
            If ishealthSlice(slices(i)) Then
                If Not slices(i).sync(host, port) Then
                    raiseError("slice cannot sync to destination " + displayHostPort(host, port) + _
                               ", sliceID " + Convert.ToString(i), errorHandle.errorType.exclamation)
                End If
            Else
                raiseError("unhealth slice found during sync to destination " + displayHostPort(host, port) _
                           + ", sliceID " + Convert.ToString(i), errorHandle.errorType.exclamation)
            End If
            i += 1
        End While

        Return True
    End Function
End Class
